/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp.net;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import ssp.topology.Node;

/**
 * ネットワークコンポーネント内のリソース情報
 * @author yamazaki
 */
public class NWresourceEntry {
    
    /**
     * 両端に接続するネットワークコンポーネント
     */
    private final Set<Node> connectedNWcomponents;
    
    /**
     * 通信帯域の最小単位
     */
    private final double bandwidthUnit;
    
    /**
     * bandwidthUnit当たりの回線利用料金
     */
    private final double chargeUnit;
    
    /**
     * QoS指標のリスト
     */
    private final List<Integer> QoSindexList;
    
    /**
     * bandwidthUnitで許容可能なコネクションの数 <br>
     * (回線容量) = (bandwidthUnit) * (capacity)
     */
    private final int capacity;
    
    /**
     * サービスのために予約されたリソース
     */
    private int reservedResource;
    
    /**
     * コンストラクタ
     * @param connectedNWcomponents 両端に接続するネットワークコンポーネント
     * @param bandwidthUnit 通信帯域の最小単位
     * @param QoSindexList QoS指標のリスト
     * @param capacity 許容可能なコネクションの数
     */
    protected NWresourceEntry(Set<Node> connectedNWcomponents, double bandwidthUnit, double chargeUnit, List<Integer> QoSindexList, int capacity) {
        this.connectedNWcomponents = new HashSet<Node>(connectedNWcomponents);
        this.bandwidthUnit = bandwidthUnit;
        this.chargeUnit = chargeUnit;
        this.QoSindexList = new ArrayList<Integer>(QoSindexList);
        this.capacity = capacity;
        this.reservedResource = 0;
    }

    /**
     * @return the connectedNWcomponents
     */
    protected Set<Node> getConnectedNWcomponents() {
        return connectedNWcomponents;
    }

    /**
     * @return the bandwidthUnit
     */
    protected double getBandwidthUnit() {
        return bandwidthUnit;
    }
    
    /**
     * 指定の帯域を利用するための利用料金を返す
     * @param bandwidth 利用帯域
     * @return 利用料金
     */
    protected double getCharge(double bandwidth) {
        return Math.ceil(bandwidth / bandwidthUnit) * chargeUnit;
    }

    /**
     * 指定のindexのQoS値を返す
     * @param index
     * @return QoS値
     */
    protected int getQoSindex(int index) {
        return this.QoSindexList.get(index);
    }
    
    /**
     * @return the QoSindexList
     */
    public List<Integer> getQoSindexList() {
        return this.QoSindexList;
    }

    /**
     * @return the capacity
     */
    protected int getCapacity() {
        return capacity;
    }

    /**
     * @return the reservedResource
     */
    protected int getReservedResource() {
        return reservedResource;
    }

    /**
     * リソースを予約する
     * @param delta 新たに予約するリソース量
     * @return 予約に成功すればtrue
     */
    protected boolean reserveResources(int delta) {
        if(this.reservedResource + delta > capacity) {
            return false;
        }
        this.reservedResource += delta;
        return true;
    }
    
    /**
     * リソースを解放する
     * @param delta 解放するリソース量
     */
    protected void releaseResources(int delta) {
        if(this.reservedResource - delta < 0) {
            throw new IllegalArgumentException();
        }
        this.reservedResource -= delta;
    }
    
}
